
# This trigger is meant to disallow filenames that may cause problems with
# unix and windows filesystems, independently from what svn may or may not
# disallow itself)

import posixpath
import re
import svn.fs

# Disallow all kinds of whitespace (space, tab, nl)
BADCHARS_WS = { " "  : "' ' (space)",
                "\t" : "'\t' (tab)",
                "\n" : "LF (new line)",
                "\r" : "CR (carriage return)",
              }
# These make windows unhappy
BADCHARS_OTHER = {  "*" : "'*'",
                    "?" : "'?'",
                    "\\" : "'\\' (backslash)",
                    ":" : "':' (colon)",
                    ";" : "';' (semi-colon)",
                    "'" : "\"'\" (single quote)",
                    '"' : "'\"' (double quote)",
                 }
BADCHARS = BADCHARS_WS
BADCHARS.update(BADCHARS_OTHER)

# As per http://msdn2.microsoft.com/en-us/library/aa365247.aspx
BAD_WINDOWS_FILENAMES = ( "CON", "PRN", "AUX", "NUL",
    "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
    "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
     )

def RunHook(hi, logger):

  for (path, cl) in hi.paths_changed.iteritems():
    # If the file already got in somehow, any damage is already done.
    # And we certainly want folks to be able to remove paths with bad
    # names.  So we only block adds.  Replace, therefore, is also fine.
    if cl.change_kind != svn.fs.path_change_add:
      continue

    name = posixpath.basename(path)

    for char in BADCHARS.keys():
      #print "looking for %s in %s" % (char, name)
      if char in path:
        return "%s is forbidden in pathname '%s'" % (BADCHARS[char], path)

    for bad_windows_filenames in BAD_WINDOWS_FILENAMES:
      # allow any of AUX and AUX.foo names
      pattern = "^" + bad_windows_filenames + "(\.[^/]*)*$(?i)"
      #print "Looking for %s in %s" % (pattern, name)
      if re.match(pattern, name):
        return "Sorry, %s contains %s, which is not compatible with Windows" \
                                                % (path, bad_windows_filenames)

  return 0
